/* enum */
import ComponentNameEnum from '@model/enum/ComponentNameEnum'
/* hooks */
import { useBizRoleSelectFetchRoleList } from '@src/component/business/BizRoleSelect/hooks'
/* model */
import Role from '@model/entity/Role/Role'
import { BizRoleSelectOption } from '@src/component/business/BizRoleSelect/model'
/* scss */
import '@src/component/business/BizRoleSelect/index.scss'
/* vue */
import { ComponentInstance, defineComponent, CreateElement, PropType, computed, watch, VNode } from 'vue'
/* locales */
import { t } from '@src/locales'
/* util */
import { rolesToOptions, transformRoleList } from '@src/component/business/BizRoleSelect/util'
import { isArray, isEmpty, isFalsy, isNotArray, isNotEmpty } from '@src/util/type'
import { getProductLineRoleName, isCustomerServiceCloudProductAndBusinessServiceCloudProduct } from '@shb-lib/tenant'

export type BizRoleSelectProps = {
  // 是否可清空
  clearable: boolean;
  // 是否折叠标签
  collapseTags: boolean;
  // 是否禁用
  disabled: boolean;
  // 是否可搜索
  filterable: boolean;
  // 获取 label
  getLabel: (option: BizRoleSelectOption) => string;
  // 是否强制树形模式
  isForceTreeMode: boolean;
  // 是否只显示 服务云角色
  isOnlyShowBusinessServiceCloudRole: boolean;
  // 是否多选
  multiple: boolean;
  // 占位符
  placeholder: string;
  // 角色列表
  roles: Role[];
  // 选中的角色id
  value: string | string[];
}

export interface BizRoleSelectSetupState {
  
}

export enum BizRoleSelectEmitEventNameEnum {
  Input = 'input',
  Change = 'change'
}

export type BizRoleSelectInstance = ComponentInstance & BizRoleSelectSetupState

/** 
 * @description 角色选择器
 * -- 暂不支持服务商角色
*/
export default defineComponent({
  name: ComponentNameEnum.BizRoleSelect,
  emits: [
    BizRoleSelectEmitEventNameEnum.Input,
    BizRoleSelectEmitEventNameEnum.Change
  ],
  props: {
    /** 
     * @description 是否可清空
    */
    clearable: {
      type: Boolean as PropType<boolean>,
      default: false
    },
    /** 
     * @description 是否折叠标签
    */
    collapseTags: {
      type: Boolean as PropType<boolean>,
      default: false
    },
    /** 
     * @description 是否禁用
    */
    disabled: {
      type: Boolean as PropType<boolean>,
      default: false
    },
    /** 
     * @description 是否可搜索
    */
    filterable: {
      type: Boolean as PropType<boolean>,
      default: false
    },
    getLabel: {
      type: Function as PropType<(option: BizRoleSelectOption) => string>,
      default: (option: BizRoleSelectOption) => option.label
    },
    /** 
     * @description 是否强制树形模式
    */
    isForceTreeMode: {
      type: Boolean,
      default: false
    },
    /** 
     * @description 是否只显示 服务云 角色
    */
    isOnlyShowBusinessServiceCloudRole: {
      type: Boolean,
      default: false
    },
    /** 
     * @description 是否多选
    */
    multiple: {
      type: Boolean as PropType<boolean>,
      default: false
    },
    /** 
     * @description 占位符
    */
    placeholder: {
      type: String as PropType<string>,
      // 请选择角色
      default: t('common.placeholder.selectRole')
    },
    /** 
     * @description 角色列表
    */
    roles: {
      type: Array as PropType<Role[]>,
      default: () => []
    },
    /** 
     * @description 选中的角色id
    */
    value: {
      type: [String, Array] as PropType<string | string[]>,
      default: ''
    }
  },
  setup(props: BizRoleSelectProps, { emit }) {
    
    const { roleList, fetchRoleList } = useBizRoleSelectFetchRoleList()
    
    // props 角色列表是否不为空
    const isPropsRoleNotEmpty = computed(() => isArray(props.roles) && isNotEmpty(props.roles))
    
    // props 角色列表是否为空
    const isPropsRoleEmpty = computed(() => isNotArray(props.roles) || isEmpty(props.roles))
    
    // 是否只显示服务云角色
    const isOnlyShowBusinessServiceCloudRole = computed(() => Boolean(props?.isOnlyShowBusinessServiceCloudRole));
    
    /** 
     * @description 是否处于树形模式
    */
    const isTreeMode = computed(() => {
      
      // 如果配置了仅显示 服务云 角色，则取消树形模式
      if (isOnlyShowBusinessServiceCloudRole.value) {
        return false
      }
      
      return props.isForceTreeMode || isCustomerServiceCloudProductAndBusinessServiceCloudProduct()
    })
    
    const originRoles = computed(() => {
      // 如果 props 传入的角色列表不为空，则使用 props 传入的角色列表
      return isPropsRoleNotEmpty.value ? props.roles : roleList.value
    })
    
    /** 
     * @description 角色列表
    */
    const roles = computed(() => {
      
      const options = {
        isOnlyShowBusinessServiceCloudRole: isOnlyShowBusinessServiceCloudRole.value
      }
      
      // 按产品线处理角色列表
      return transformRoleList(originRoles.value, options)
      
    })
    
    /** 
     * @description el-select 角色列表
    */
    const options = computed(() => {
      return rolesToOptions(roles.value)
    })
    
    const value = computed(() => props.value)
    
    return {
      isTreeMode,
      isPropsRoleEmpty,
      options,
      originRoles,
      value,
      fetchRoleList
    }
  },
  watch: {
    isPropsRoleEmpty: {
      immediate: true,
      handler(newValue) {
        newValue && this.initFetchRoleList()
      }
    }
  },
  methods: {
    /** 
     * @description 初始化获取角色列表
    */
    initFetchRoleList() {
      
      const params = {
        pageNum: 1,
        pageSize: 500
      }
      
      this.fetchRoleList(params)
      
    },
    onValueChangeHandler(value: string | string[]) {
      this.$emit(BizRoleSelectEmitEventNameEnum.Input, value)
      this.$emit(BizRoleSelectEmitEventNameEnum.Change, value)
    },
    /** 
     * @description 渲染基础选择器
    */
    renderBaseSelect(h: CreateElement, children: VNode[]) {
      
      const scopedSlots = {
        multiple: (props: { item: { value: string, label: string } }) => {
          
          const value = props?.item?.value || ''
          const label = props?.item?.label || ''
          
          if (isFalsy(this.isTreeMode)) {
            return label
          }
          
          const role = this.originRoles.find(item => item?.id === value)
          const productLine = role?.productLine || ''
          
          if (isFalsy(value) || isFalsy(role) || isFalsy(label) || isFalsy(productLine)) {
            return
          }
          
          // 暂时不添加角色前缀了，直接返回原始的角色名称
          const isUseOriginName = true
          return getProductLineRoleName(role!, isUseOriginName)
        }
      }
      
      return (
        <publink-select
          clearable={this.clearable}
          collapseTags={this.collapseTags}
          disabled={this.disabled}
          filterable={this.filterable}
          isOnlyUseMultipleSlot
          multiple={this.multiple}
          placeholder={this.placeholder}
          scopedSlots={scopedSlots}
          value={this.value}
          onInput={this.onValueChangeHandler}
        >
          { children }
        </publink-select>
      )
    },
    /** 
     * @description 渲染默认选择 一级的角色列表
    */
    renderDefaultSelect(h: CreateElement) {
      const children = this.options.map(this.renderSelectOption)
      return this.renderBaseSelect(h, children)
    },
    /** 
     * @description 渲染默认选择配置项
    */
    renderSelectOption(option: BizRoleSelectOption) {
      
      const label = this.getLabel(option)
      
      return (
        <el-option
          key={option.value}
          label={label}
          value={option.value}>
          <span class="flex-x">{label}{option.qualificationNames && <span class="overHideCon-1 flex-1 mar-l-8 font-12 qualificationManagement-info">{this.$t('qualificationManagement.view.label13')}：{option.qualificationNames.join('，')}</span>}</span>
          </el-option>
      )
    },
    /** 
     * @description 渲染默认选择配置项组
    */
    renderOptionGroup(option: BizRoleSelectOption) {
      
      const children: BizRoleSelectOption[] = option?.children || []
      
      return (
        <el-option-group
          key={option.label}
          label={option.label}
        >
          { children.map(this.renderSelectOption) }
        </el-option-group>
      )
    },
    /** 
     * @description 渲染树形选择
    */
    renderTreeSelect(h: CreateElement) {
      const children = this.options.map(this.renderOptionGroup)
      return this.renderBaseSelect(h, children)
    }
  },
  render(h: CreateElement) {
    return (
      <div>
        { this.isTreeMode ? this.renderTreeSelect(h) : this.renderDefaultSelect(h) }
      </div>
    )
  }
})
